package cn.wlinker.driver.modbus.tcp.utils;

import cn.hutool.log.StaticLog;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;

/**
 * modbus4j写入数据
 *
 * @author gxsjx
 * @version 1.0
 * @date 2022/10/9
 * Copyright © wlinker.cn
 */
public class Modbus4jWriter {

	private final ModbusMaster master;

	public Modbus4jWriter(String ip, Integer port) {
		this.master = ModbusMasterHelper.getMaster(ip,port);
	}

	/**
	 * 写 [01 Coil Status(0x)]写一个 function ID = 5
	 * 
	 * @param slaveId
	 *            slave的ID
	 * @param writeOffset
	 *            位置
	 * @param writeValue
	 *            值
	 * @return 是否写入成功
	 */
	public boolean writeCoil(int slaveId, int writeOffset, boolean writeValue)
			throws ModbusTransportException {
		// 创建请求
		WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
		// 发送请求并获取响应对象
		WriteCoilResponse response = (WriteCoilResponse) master.send(request);
		if (response.isException()) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 写[01 Coil Status(0x)] 写多个 function ID = 15
	 * 
	 * @param slaveId
	 *            slaveId
	 * @param startOffset
	 *            开始位置
	 * @param data
	 *            写入的数据
	 * @return 是否写入成功
	 */
	public boolean writeCoils(int slaveId, int startOffset, boolean[] data)
			throws ModbusTransportException {
		// 创建请求
		WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, data);
		// 发送请求并获取响应对象
		WriteCoilsResponse response = (WriteCoilsResponse) master.send(request);
		if (response.isException()) {
			return false;
		} else {
			return true;
		}

	}

	/***
	 * 写[03 Holding Register(4x)] 写一个 function ID = 6
	 * 
	 * @param slaveId 从机id
	 * @param writeOffset 开始位置
	 * @param writeValue 写入的值
	 * @return 是否写入成功
	 */
	public boolean writeHoldingRegister(int slaveId, int writeOffset, short writeValue)
			throws ModbusTransportException {
		// 创建请求对象
		WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
		WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);
		if (response.isException()) {
			StaticLog.error(response.getExceptionMessage());
			return false;
		} else {
			return true;
		}

	}

	/**
	 * 
	 * 写入[03 Holding Register(4x)]写多个 function ID=16
	 * 
	 * @param slaveId
	 *            modbus的slaveID
	 * @param startOffset
	 *            起始位置偏移量值
	 * @param data
	 *            写入的数据
	 * @return 返回是否写入成功
	 */
	public boolean writeHoldingRegisters(int slaveId, int startOffset, short[] data)
			throws ModbusTransportException {
		// 创建请求对象
		WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, data);
		// 发送请求并获取响应对象
		ModbusResponse response = master.send(request);
		if (response.isException()) {
			StaticLog.error(response.getExceptionMessage());
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 写入数字类型的模拟量（如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long）
	 * 
	 * @param slaveId 从机ID
	 * @param offset 起始位置
	 * @param value
	 *            写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long
	 * @param dataType
	 *            ,com.serotonin.modbus4j.code.DataType
	 */
	public void writeHoldingRegisterByDataType(int slaveId, int offset, String value, int dataType)
			throws ModbusTransportException, ErrorResponseException {
		// 类型
		BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);
		master.setValue(locator, value);
	}

}